import { ElMessage } from 'element-plus';

/**
 * Socket.io工具类，封装WebSocket连接、消息发送和接收等操作
 */
import { io, Socket } from 'socket.io-client';


export class SocketService {
  private socket: Socket | null = null;
  private readonly host: string;
  private readonly protocol: string;
  private reconnectInterval: number = 3000; // 重连间隔(ms)
  private maxReconnectAttempts: number = 10; // 最大重连次数
  private reconnectAttempts: number = 0; // 当前重连次数
  private isConnected: boolean = false;

  /**
   * 构造函数
   */
  constructor() {
    // 从环境变量获取WebSocket主机，默认为localhost:5000
    this.host = import.meta.env.VITE_WS_HOST || 'localhost:5000';
    this.protocol = window.location.protocol === 'https:' ? 'https:' : 'http:';
  }

  /**
   * 初始化Socket.io连接
   * @param userId - 用户ID，用于登录认证
   */
  public init(userId: number): void {
    if (this.socket) {
      this.socket.disconnect();
    }

    const url = `${this.protocol}//${this.host}`;
    console.log(`[${new Date().toLocaleString()}] [INFO] 尝试连接到Socket.io服务器: ${url}`);

    this.socket = io(url, {
      transports: ['websocket'],
      autoConnect: true,
      reconnection: false // 禁用自动重连，使用自定义重连逻辑
    });

    this.socket.on('connect', () => {
      this.isConnected = true;
      this.reconnectAttempts = 0;
      console.log(`[${new Date().toLocaleString()}] [INFO] Socket.io连接已建立: ${url}`);

      // 直接发送登录事件，不通过message包装
      this.socket?.emit('login', { data: { userId } });
      console.log(`[${new Date().toLocaleString()}] [INFO] 发送Socket.io登录事件: userId=${userId}`);
    });

    this.socket.on('message', (data) => {
      try {
        this.handleMessage(data);
      } catch (error) {
        console.error(`[${new Date().toLocaleString()}] [ERROR] 解析Socket.io消息失败:`, error);
      }
    });

    this.socket.on('disconnect', () => {
      this.isConnected = false;
      console.log(`[${new Date().toLocaleString()}] [INFO] Socket.io连接已关闭`);

      // 尝试重连
      if (this.reconnectAttempts < this.maxReconnectAttempts) {
        setTimeout(() => {
          this.reconnectAttempts++;
          console.log(`[${new Date().toLocaleString()}] [INFO] 尝试第 ${this.reconnectAttempts} 次重连`);
          this.init(userId);
        }, this.reconnectInterval);
      } else {
        console.error(`[${new Date().toLocaleString()}] [ERROR] 达到最大重连次数，停止重连`);
        ElMessage.error('Socket.io连接失败，请刷新页面重试');
      }
    });

    this.socket.on('connect_error', (error) => {
      console.error(`[${new Date().toLocaleString()}] [ERROR] Socket.io连接错误:`, error);
    });
  }

  /**
   * 发送消息
   * @param type - 消息类型
   * @param data - 消息数据
   */
  public send(type: string, data: any): void {
    if (!this.socket || !this.isConnected) {
      console.error(`[${new Date().toLocaleString()}] [ERROR] Socket.io未连接，无法发送消息`);
      return;
    }

    try {
      this.socket.emit('message', {
        type,
        data
      });
      console.log(`[${new Date().toLocaleString()}] [INFO] 发送Socket.io消息: ${type}`, data);
    } catch (error) {
      console.error(`[${new Date().toLocaleString()}] [ERROR] 发送Socket.io消息失败:`, error);
    }
  }

  /**
   * 关闭Socket.io连接
   */
  public close(): void {
    if (this.socket) {
      this.socket.disconnect();
      this.socket = null;
      this.isConnected = false;
      console.log(`[${new Date().toLocaleString()}] [INFO] Socket.io连接已手动关闭`);
    }
  }

  /**
   * 添加事件监听器
   * @param eventName - 事件名称
   * @param callback - 回调函数
   */
  public on(eventName: string, callback: (data: any) => void): void {
    if (this.socket) {
      this.socket.on(eventName, callback);
    }
  }

  /**
   * 移除事件监听器
   * @param eventName - 事件名称
   * @param callback - 回调函数（可选，不提供则移除所有该事件的监听器）
   */
  public off(eventName: string, callback?: (data: any) => void): void {
    if (this.socket) {
      if (callback) {
        this.socket.off(eventName, callback);
      } else {
        this.socket.removeAllListeners(eventName);
      }
    }
  }

  /**
   * 处理接收到的消息
   * @param data - 消息数据
   */
  private handleMessage(data: any): void {
    console.log(`[${new Date().toLocaleString()}] [INFO] 收到Socket.io消息:`, data);
  }

  /**
   * 检查Socket.io连接状态
   * @returns 是否连接
   */
  public get connected(): boolean {
    return this.isConnected;
  }
}

// 创建单例实例
export const socketService = new SocketService();